import Foundation;
import JL_OTALib;
import JL_HashPair;

@objcMembers
class JieliOtaManager: NSObject, JL_OTAManagerDelegate, JLHashHandlerDelegate {

    var plugin: JieliBleOtaPlugin?

    let otaManager = JL_OTAManager()
    let hashPairManager = JLHashHandler();
    
    // 正在等待继续升级
    var waiting4ContinuingUpdate = false;
    // 正在等待重连
    var waiting4Reconnect = false;

    // 已完成 hash pair
    var alreadyHashPaired = false;
    
    // OTA 文件路径
    var otaFilePath :String? = nil;

    override
    init() {
        super.init()
        self.otaManager.delegate = self;
        self.hashPairManager.delegate = self;
    }

    public func reset() {
        waiting4Reconnect = false;
        waiting4ContinuingUpdate = false;
    }
    
    public func setPluginInstace(plugin: JieliBleOtaPlugin) {
        self.plugin = plugin;
    }

    public func onDataReceived(bytes: Data){
        let hexString = bytes.map { String(format: "%02X", $0) }.joined();
        print("on data received, already paired?\(alreadyHashPaired) ,\(bytes), \(hexString)");
        if(!alreadyHashPaired){
            print("forward to hash pair sdk");
            self.hashPairManager.inputPairData(bytes);
            return;
        }
       
        self.otaManager.cmdOtaDataReceive(bytes);
    }

    
    func start2Ota(filePath: String) {
        self.otaFilePath = filePath;
        let bytes = getFileData(filePath: filePath);
        self.otaManager.cmdOTAData(bytes);
    }

    func getFileData(filePath: String) -> Data {
        do {
            let data = try Data(contentsOf: URL(fileURLWithPath: filePath));
            return data;
        } catch {
            print("Error reading data from local file: \(error.localizedDescription)");
        }
        
        return Data();
    }

    public func requestDeviceFirmwareState(){
        if (alreadyHashPaired) {
            otaManager.cmdTargetFeature();
            return;
        }
        
        // 进行 hash pair
        hashPairManager.bluetoothPairingKey(nil, result: { [weak self] ret in
            guard let self = self else { return }
            print("requestHashPair, ret: \(ret)");
            if ret {
                alreadyHashPaired = true;
                
                // 查询设备固件状态
                self.otaManager.cmdTargetFeature();
            } else {
                // pair 失败
                self.plugin!.notifyDeviceFirmwareStatusRequestFailed();
            }
        });
    }

    
    public func onConnected(identifier: String, name: String) {
        otaManager.mBLE_NAME = name;
        otaManager.mBLE_UUID = identifier;
        
        if (!waiting4Reconnect || !waiting4ContinuingUpdate) {
            return;
        }
        
        // 已重连，正在等待继续升级
        
        waiting4Reconnect = false;
        
        hashPairManager.hashResetPair();
        
        // 查询设备固件状态以继续升级
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            self.requestDeviceFirmwareState();
        }
    }

    public func onDisconnected() {
        alreadyHashPaired = false;
        
        if (waiting4Reconnect) {
            plugin!.connectLink();
        }
    }


    /*  JL_OTAManagerDelegate implementation START   */

    func otaDataSend(_ data: Data) {
        let hexString = data.map { String(format: "%02X", $0) }.joined();
        print("ota data send, \(data), \(hexString)");
      
        // 处理即将发送的数据
        self.plugin!.writeData(bytes:data);
    }

    // 请求设备固件状态回调
    func otaFeatureResult(_ manager: JL_OTAManager) {
        if (!waiting4ContinuingUpdate) {
            self.plugin!.notifyDeviceFirmwareStatusRequested(firmwareBroken: manager.otaStatus == JL_OtaStatus.force);
            return;
        }
       
        // 继续升级流程
        start2Ota(filePath: self.otaFilePath!);
    }

    // 升级过程状态回调
    func otaUpgradeResult(_ result: JL_OTAResult, progress: Float) {
        print("otaUpgradeResult, state: \(result.rawValue) , progress: \(progress)");
        
        if (result == JL_OTAResult.success) {
            // 升级成功
            plugin!.notifyOtaUpdateSuccess();
            return;
        }
        
        
        if (result == JL_OTAResult.reconnect) {
            // SDK 请求重连
            plugin!.connectLink();
            return;
        }
        
        
        if (result == JL_OTAResult.reboot || result == JL_OTAResult.reconnectWithMacAddr) {
            // 不处理这些事件
            return;
        }
        
        
        
        if (result == JL_OTAResult.preparing || result == JL_OTAResult.prepared) {
            // preparing | prepared 也即正在下载 bootloader 固件，定义为 type 0
            self.plugin!.notifyOtaProgressChanged(type: 0, progress: progress * 100);
            
            if (result == JL_OTAResult.prepared) {
                //  Bootloader 下载完成，设备端准备重启（连接断开）
                waiting4Reconnect = true;
                waiting4ContinuingUpdate = true;
            }
        } else if (result == JL_OTAResult.upgrading) {
            // upgrading 也即正在下载应用程序固件，定义为 type 1
            self.plugin!.notifyOtaProgressChanged(type: 1, progress: progress * 100);
        } else {
            // 其余均为升级失败
            self.plugin!.notifyOtaUpdateFailed(code: String(result.rawValue));
        }
    }
        

    func otaCancel() {
        // 处理取消OTA升级
        print("otaCancel");

    }

    /*  JL_OTAManagerDelegate implementation END   */
    
    /*  JLHashHandlerDelegate implementation START   */

    func hash(onPairOutputData data: Data) {
        print("send hash apir data, \(data)");
        let hexString = data.map { String(format: "%02X", $0) }.joined();
        
        print(hexString)
        self.plugin!.writeData(bytes:data);
    }

     /*  JLHashHandlerDelegate implementation END   */


    
}
